#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/configfs.h>
#include <linux/kernel.h>


struct config_group mygroup;

struct myitem {
    struct config_item item;
    void *addr;
    int size;
};

//在/sys/kernel/config/myconfigfs/mygroup目录下删除新目录时释放
void myitem_release(struct config_item *item){

    struct myitem *myitem;
    printk("%s\n", __func__);

    myitem = container_of(item, struct myitem, item);
    kfree(myitem);
}

//对read文件读
ssize_t myread_show(struct config_item *item, char *str){
    struct myitem *myitem;
    printk("%s\n", __func__);

    myitem = container_of(item, struct myitem, item);
    memcpy(str, myitem->addr, myitem->size);
    return myitem->size;
}

//对write文件写
ssize_t mywrite_store(struct config_item *item, const char *str, size_t size){
    struct myitem *myitem;
    printk("%s\n", __func__);

    myitem = container_of(item, struct myitem, item);
    myitem->addr = kmemdup(str, size, GFP_KERNEL);
    myitem->size = size;
    
    return size;
}


CONFIGFS_ATTR_RO(my, read);
CONFIGFS_ATTR_WO(my, write);


//定义指针数组, 当创建新目录时会自动创建两个文件read和write
struct configfs_attribute *my_attr[] ={
    &myattr_read,
    &myattr_write,
    NULL,
};


struct configfs_item_operations myitem_ops = {
    .release = &myitem_release,
};


static struct config_item_type mygroup_item_type = {
    .ct_owner = THIS_MODULE,
    .ct_item_ops = &myitem_ops,
    .ct_group_ops = NULL,
    .ct_bin_attrs = NULL,
    .ct_attrs = my_attr,
};


//在/sys/kernel/config/myconfigfs/mygroup目录下可以创建新目录
struct config_item *mygroup_make_item(struct config_group *group, const char *name){
    struct myitem *myconfig_item;

    printk("%s\n", __func__);
    myconfig_item = kzalloc(sizeof(*myconfig_item), GFP_KERNEL);
    config_item_init_type_name(&myconfig_item->item, name, &mygroup_item_type);

    return &myconfig_item->item;
}


//当实现drop_item函数时,会调用该函数,使用config_item_put调用release函数
void mydrop_item(struct config_group *group, struct config_item *item){
    printk("%s\n", __func__);
    config_item_put(item);
}

struct configfs_group_operations mygroup_ops = {
    .make_item = &mygroup_make_item,
    .drop_item = mydrop_item,   
    .make_group= NULL,  //当make_item和make_group都实现时,创建目录操作会执行make_group不会执行make_item, 来实现多级目录
};

static struct config_item_type mygroup_config_item_type = {
    .ct_owner = THIS_MODULE,
    .ct_item_ops = NULL,
    .ct_group_ops = &mygroup_ops,
    .ct_bin_attrs = NULL,
};

static struct config_item_type myconfig_item_type = {
    .ct_owner = THIS_MODULE,
    .ct_item_ops = NULL,
    .ct_group_ops = NULL,
    .ct_bin_attrs = NULL,
};

static struct configfs_subsystem myconfigfs_subsystem ={
    .su_group = {
        .cg_item = {
            .ci_namebuf = "myconfigfs",
            .ci_type = &myconfig_item_type,
        }
    },
};

static int myconfigfs_init(void){

    config_group_init(&myconfigfs_subsystem.su_group);
    configfs_register_subsystem(&myconfigfs_subsystem);   //会产生/sys/kernel/config/myconfigfs目录

    config_group_init_type_name(&mygroup, "mygroup", &mygroup_config_item_type);
    configfs_register_group(&myconfigfs_subsystem.su_group, &mygroup);  //会产生/sys/kernel/config/myconfigfs/mygroup目录

    return 0;
}

static void myconfigfs_exit(void){
    
    configfs_unregister_subsystem(&myconfigfs_subsystem);
}



module_init(myconfigfs_init);
module_exit(myconfigfs_exit);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("DACHEN");
MODULE_VERSION("V1.0");

